package cn.wp.ewallet.wallet.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.wp.ewallet.common.extension.constant.EwalletConstant;
import cn.wp.ewallet.common.extension.properties.EthProperties;
import cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant;
import cn.wp.ewallet.wallet.extension.util.EwalleTransactionUtil;
import cn.wp.ewallet.wallet.extension.util.EwalletWalletUtil;
import cn.wp.ewallet.wallet.model.dto.MentionMoneyInfoDto;
import cn.wp.ewallet.wallet.model.dto.TransAccountLogDto;
import cn.wp.ewallet.wallet.model.dto.WalletAccountInfoDto;
import cn.wp.ewallet.wallet.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
import org.web3j.utils.Convert;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

/**
 * 转账交易状态确认服务
 * Created by zhangyongli on 2020/1/14
 */
@Slf4j
@Service
public class TransferStatusConfirmServiceImpl implements TransferStatusConfirmService {

    @Autowired
    private TransAccountLogService transAccountLogService;

    @Autowired
    private AccountInfoService accountInfoService;

    @Autowired
    private WalletInfoService walletInfoService;

    @Autowired
    private AutoCollectService autoCollectService;

    @Autowired
    private MentionMoneyInfoService mentionMoneyInfoService;

    @Autowired
    private EthProperties ethProperties;

    @Override
    public void execute() {

        //查询所有在确认中的交易记录
        List<TransAccountLogDto> list = transAccountLogService.getPendingList();
        if (CollectionUtil.isEmpty(list)) {
            return ;
        }
        EwalleTransactionUtil walleUtil = EwalleTransactionUtil.getInstance();
        //连接web3j
        Web3j web3j = walleUtil.getDefaultConect(ethProperties.getNetwork());

        for (TransAccountLogDto dto: list) {
            try {
                EthGetTransactionReceipt result = walleUtil.getTransactionReceiptByHex(web3j, dto.getThId());
                //无数据或无结果时，认为交易没有打包，不做任何处理
                if (null == result || null == result.getResult() || null == result.getResult().getStatus()) {
                    continue;
                }
                process(result.getResult().getStatus(), result.getResult().getGasUsed(), dto, web3j, walleUtil);

            } catch (IOException e) {
                log.error("查询交易收据失败，msg={}", e.getMessage());
                e.printStackTrace();
            }
        }

    }

    /**
     * 处理查询结果，成功-更新状态完成，失败，更新状态完成，回退资产信息
     * @param status
     * @param dto
     */
    @Transactional
    protected void process(String status, BigInteger gasUsed, TransAccountLogDto dto, Web3j web3j, EwalleTransactionUtil walleUtil) {

        TransAccountLogDto transAccountLogDto = new TransAccountLogDto();
        transAccountLogDto.setLogId(dto.getLogId());
        transAccountLogDto.setServiceCharge(Convert.toWei(gasUsed.toString(), Convert.Unit.GWEI));
        try {
            Integer result = Integer.valueOf(status.replace(EwalletConstant.HEX_ID, ""));
            if (EwalletWalletConstant.TRANSACTION_STATUS_SUCCESS == result) {
                //成功，更新转账交易状态
                transAccountLogDto.setOperResult(EwalletWalletConstant.TRANSFER_OPER_RESULT_SUCCESS);
                transAccountLogService.modifyTransAccountLog(transAccountLogDto);
                //以太币转账时，需要再次出发归集操作
                if (EwalletWalletConstant.MONEY_TYPE_ETH.equals(dto.getMoneyTypeId())) {
                    autoCollectService.executeCollectByAddress(dto.getAddressTo(), web3j, walleUtil);
                }

            }else {
                //失败，更新转交易状态
                transAccountLogDto.setOperResult(EwalletWalletConstant.TRANSFER_OPER_RESULT_FAILED);
                transAccountLogService.modifyTransAccountLog(transAccountLogDto);
                //提币操作，需要回退提币金额+手续费
                if (StringUtils.isNotEmpty(dto.getReqOrderId())) {
                    MentionMoneyInfoDto mentionMoneyInfoDto = mentionMoneyInfoService.getMentionMoneyReqOrderById(dto.getReqOrderId());
                    accountInfoService.saveAccountChange(dto.getAddressFrom(), mentionMoneyInfoDto.getTotal(), EwalletWalletConstant.ACCOUNT_SUBTRACT, EwalletWalletConstant.ACCOUNT_CHARGE_CASE_WITHFRAW_MONEY, mentionMoneyInfoDto.getMoneyTypeId(), EwalletWalletConstant.ACCOUNT_TYPE_AVAILABLE);
                }else {
                    //非ETH手续费转账，链上资产账户回退，因为已经
                    if (!EwalletWalletConstant.MONEY_TYPE_ETH.equals(dto.getMoneyTypeId())) {
                        accountInfoService.saveAccountChange(dto.getAddressFrom(), dto.getTransAmount(), EwalletWalletConstant.ACCOUNT_ADD, EwalletWalletConstant.ACCOUNT_CHARGE_CASE_AUTO_COLLECT, dto.getMoneyTypeId(), EwalletWalletConstant.ACCOUNT_TYPE_WEB);
                    }
                }

            }
        }catch (Exception e) {
            log.error("交易状态异常，txHash={}", dto.getThId());
            e.printStackTrace();
        }

    }
}
